home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianGarbageMan.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
10KB
|
484 lines
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianLists.h"
#include "ScianIDs.h"
#include "ScianGarbageMan.h"
#include "ScianWindows.h"
#include "ScianDialogs.h"
#include "ScianNetObjects.h"
#define MARKED 1
#define CLEARED 0
#define ISDELETED 69234269
#define IsDeleted(thing) ((thing) -> garbageFlag == ISDELETED)
int TrashDayFlag = 0;
ObjPtr globalObjectList = NULLOBJ;
GlobalReferenceListPtr globalReferenceList = (GlobalReferenceListPtr) 0;
ObjPtr deletedList = NULLOBJ;
long int freedObjects = 0;
void InitMem()
{
#if MALLOPT
/* HAK optimizing adjustments for the new malloc */
if (mallopt(M_MXFAST, 128))
{
struct mallinfo mi;
fprintf(stderr, "Uh-oh! malloc'ed something before mallopt call!\n");
mi = mallinfo();
fprintf(stderr,"arena=%d, ordblks=%d, smblks=%d, hblkhd=%d, hblks=%d\n",
mi.arena, mi.ordblks, mi.smblks, mi.hblkhd, mi.hblks);
fprintf(stderr,"usmblks=%d, fsmblks=%d, uordblks=%d, fordblks=%d, keepcost=%d\n",
mi.usmblks, mi.fsmblks, mi.uordblks, mi.fordblks, mi.keepcost);
}
#endif
}
void KillMem()
{
}
void AddToGlobalList(obj)
ObjPtr obj;
{
obj -> gNext = globalObjectList;
globalObjectList = obj;
}
/* took rNext out of Obj since only a tiny percentage of objects use it. */
#if 0
void AddToReferenceList(obj)
ObjPtr obj;
{
if (obj->refCount > 0)
{
++(obj -> refCount);
}
else if (obj->refCount == 0)
{
obj -> rNext = globalReferenceList;
globalReferenceList = obj;
++(obj -> refCount);
}
else
{
ReportError("AddToReferenceList", "found negative refCount!");
}
}
#else
void AddToReferenceList(obj)
ObjPtr obj;
{
GlobalReferenceListPtr temp;
if (!obj)
return;
temp = Alloc(sizeof(struct GlobalReferenceListStruct));
temp -> obj = obj;
temp -> next = globalReferenceList;
globalReferenceList = temp;
}
#endif
#if 0
int RemoveFromReferenceList(obj)
ObjPtr obj;
{
ObjPtr *runner;
if (!obj)
return true;
if (!globalReferenceList)
return false;
--(obj -> refCount);
if (obj -> refCount < 0)
ReportError("RemoveFromReferenceList", "found negative refCount!");
if (obj->refCount > 0)
{
return true;
}
runner = &globalReferenceList;
while (((*runner) -> rNext) && *runner != obj )
{
runner = &((*runner) -> rNext);
}
if (*runner == obj)
{
/* really removing the thing from the reference list this time! */
*runner = (*runner) -> rNext;
++TrashDayFlag;
return true;
}
return false;
}
#else
int RemoveFromReferenceList(obj)
ObjPtr obj;
{
GlobalReferenceListPtr *runner, temp;
if (!obj)
return true;
if (!globalReferenceList)
{
ReportError("RemoveFromReferenceList", "object not in global list");
return false;
}
runner = &globalReferenceList;
while (((*runner) -> next) && (*runner) -> obj != obj)
{
runner = &((*runner) -> next);
}
if ((*runner) -> obj == obj)
{
temp = *runner;
*runner = (*runner) -> next; /* remove ref list node. */
Free (temp);
++TrashDayFlag; /* may have been last reference to obj */
return true;
}
else
{
ReportError("RemoveFromReferenceList", "object not in global list");
return false;
}
}
#endif
void MarkVarTree(nodep)
VarsPtr nodep; /* pointer to node to delete */
/* MarkVarTree: frees space allocated to a var node and all its kids */
{
if (!nodep) return;
MarkVarTree(nodep->left);
MarkVarTree(nodep->right);
MarkObject(nodep->value);
}
ObjPtr MarkList(list)
ObjPtr list;
/*(trial) Disposes of the contents of list*/
{
ThingListPtr runner;
runner = LISTOF(list);
while (runner)
{
MarkObject(runner -> thing);
runner = runner -> next;
}
return ObjTrue;
}
/* Garbage collection routine that marks an object and all of
* its children, if it can find them...
*/
int MarkObject(thingp)
ObjPtr thingp;
{
FuncTyp marker;
if (!thingp)
return;
if (thingp == (ObjPtr) NETSTUBFLAG)
{
/* this special case ought to be handled in MarkObjectArray */
return;
}
if (IsDeleted(thingp))
{
sprintf(tempStr, "Hey! tried to mark something already deleted! 0x%lx", thingp);
ReportError("MarkObject", tempStr);
}
else if (thingp->garbageFlag != MARKED && thingp->garbageFlag != CLEARED)
{
sprintf(tempStr, "Invalid GarbageMan flag! 0x%lx.\n", thingp);
ReportError("MarkObject", tempStr);
}
if (thingp->garbageFlag == MARKED)
{
return; /* hit something already marked */
}
thingp->garbageFlag = MARKED;
Mark(thingp);
MarkVarTree(thingp->vars);
MarkObject(thingp->class);
}
int CountReferenceList()
{
int counter = 0;
GlobalReferenceListPtr runner;
runner = globalReferenceList;
while (runner)
{
++counter;
runner = runner -> next;
}
return counter;
}
int CountObjectList()
{
int counter = 0;
ObjPtr runner;
runner = globalObjectList;
while (runner)
{
++counter;
runner = runner -> gNext;
}
return counter;
}
typedef struct dStruct {
ObjPtr thing;
struct dStruct *next;
} dListNode, *dPtr;
dPtr deleteList = 0;
void TrashDay()
{
ObjPtr *prunner, temp;
GlobalReferenceListPtr runner;
FuncTyp marker;
#ifdef GCTIMES
struct tms foo, newfoo, newerfoo;
#endif
#if DISABLETRASHDAY
return;
#endif
#ifdef GCTIMES
times(&foo);
#endif
TrashDayFlag = 0;
runner = globalReferenceList;
while (runner)
{
MarkObject((runner) -> obj);
runner = runner -> next;
}
#ifdef GCTIMES
times(&newfoo);
fprintf(stderr, "marked all things, utime=%ld, stime=%ld\n",
newfoo.tms_utime - foo.tms_utime, newfoo.tms_stime - foo.tms_stime);
#endif
/*all referenced things marked, traverse all things, and dooda rite t'ing*/
prunner = &globalObjectList;
/* figuring out what happens here is left as an exercise for the reader */
while (*prunner)
{
if ( (*prunner) -> garbageFlag == MARKED)
{
(*prunner) -> garbageFlag = CLEARED;
prunner = & ((*prunner) -> gNext);
}
else if ( (*prunner) -> garbageFlag == CLEARED)
{
if (!IsPublished(*prunner))
{
temp = *prunner;
*prunner = (*prunner) -> gNext;
AddToDeleteList(temp);
}
}
else
{
/* What to do, what to do? */
sprintf(tempStr, "Illegal garbageFlag value! 0x%lx\n", *prunner);
ReportError("TrashDay", tempStr);
prunner = & ((*prunner) -> gNext);
}
}
/* call cleanup on everything */
CleanupDeleteList();
/* free everything and their delete pointer nodes */
DeleteDeleteList();
#ifdef GCTIMES
times(&newerfoo);
fprintf(stderr, "done with cleanup, utime=%ld, stime=%ld\n",
newerfoo.tms_utime - newfoo.tms_utime, newerfoo.tms_stime - newfoo.tms_stime);
fprintf(stderr, "total time: utime = %ld, stime = %ld, tot=%ld\n",
newerfoo.tms_utime - foo.tms_utime, newerfoo.tms_stime - foo.tms_stime,
(newerfoo.tms_utime - foo.tms_utime) + (newerfoo.tms_stime - foo.tms_stime));
#endif
}
AddToDeleteList(ObjPtr obj)
{
dPtr tmp;
tmp = deleteList;
deleteList = Alloc(sizeof(dListNode));
deleteList -> thing = obj;
deleteList -> next = tmp;
}
CleanupDeleteList()
{
FuncTyp cleaner;
dPtr runner;
ObjPtr ret;
runner = deleteList;
while (runner)
{
cleaner = GetMethod(runner->thing, CLEANUP);
if (cleaner)
{
ret = (* cleaner) (runner->thing, NIL);
if (!IsTrue(ret))
{
sprintf(tempStr,"CLEANUP on object 0x%x reported an error!\n", runner->thing);
ReportError("CleanupDeleteList", tempStr);
sprintf(tempStr, "obj->flags == 0x%x\n", runner->thing->flags);
ReportError("CleanupDeleteList", tempStr);
}
}
runner = runner -> next;
}
}
DeleteDeleteList()
{
dPtr temp;
while(deleteList)
{
if (IsList(deleteList->thing))
{
DeleteWithPrejudiceVarNode(deleteList->thing->vars);
DeleteMethodNode(deleteList->thing->methods);
DisposeListWithPersonalDislike(deleteList->thing);
}
else
{
DeleteWithPrejudiceVarNode(deleteList->thing->vars);
DeleteMethodNode(deleteList->thing->methods);
deleteList->thing -> garbageFlag = ISDELETED;
Free (deleteList->thing);
DecGlobalThingCount();
}
temp = deleteList -> next;
Free(deleteList);
deleteList = temp;
++freedObjects;
}
}
void DeleteWithPrejudiceVarNode(nodep)
VarsPtr nodep; /* pointer to node to delete */
/* DeleteVarNode: frees space allocated to a var node and all its kids */
{
if (!nodep) return;
DeleteWithPrejudiceVarNode(nodep->left);
DeleteWithPrejudiceVarNode(nodep->right);
Free(nodep);
}
void DisposeListWithPersonalDislike(list)
ObjPtr list;
{
while (LISTOF(list))
{
ThingListPtr next;
next = LISTOF(list) -> next;
Free(LISTOF(list));
LISTOF(list) = next;
}
LISTOF(list) = 0;
list -> garbageFlag = ISDELETED;
Free(list);
DecGlobalThingCount();
}
void DeleteWithPrejudice(obj)
ObjPtr obj;
{
FuncTyp cleaner;
ObjPtr ret;
if (IsPublished(obj))
{
fprintf(stderr, "HEY! tried to delete published object!\n");
return;
}
#if 0
if (IsPublished(obj))
{
#ifdef DEBUG
fprintf(stderr, "removing published object 0x%x\n", obj);
#endif
UnPublishObject(obj);
return;
}
#endif
if (IsRemote(obj))
{
/* fprintf(stderr, "removing remote object 0x%x\n", obj); */
}
cleaner = GetMethod(obj, CLEANUP);
if (cleaner)
{
ret = (* cleaner) (obj, NIL);
if (!IsTrue(ret))
{
sprintf(tempStr,"CLEANUP on object 0x%x reported an error!\n", obj);
ReportError("DeleteWithPrejudice", tempStr);
sprintf(tempStr, "obj->flags == 0x%x\n", obj->flags);
ReportError("DeleteWithPrejudice", tempStr);
}
}
if (IsList(obj))
{
DeleteWithPrejudiceVarNode(obj->vars);
DeleteMethodNode(obj->methods);
DisposeListWithPersonalDislike(obj);
}
else
{
DeleteWithPrejudiceVarNode(obj->vars);
DeleteMethodNode(obj->methods);
obj -> garbageFlag = ISDELETED;
Free (obj);
DecGlobalThingCount();
}
++freedObjects;
}